package com.tangcco.lockwell.utility;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


/**
 * @version 3.5.0
 * @description: The type Rsa util.
 * Copyright (C), 2020-2024, 乐考无忧
 * @date 2021/12/25 9:45
 */
public class RsaUtil {
    /**
     * String to hold name of the encryption algorithm.
     */
    private static final String ALGORITHM = "RSA";

    private static final String CHAR_SET = "utf-8";

    private static final Logger logger = LoggerFactory.getLogger(RsaUtil.class);

    /**
     * Rsa encode string.
     *
     * @param publicCertificate the public certificate
     * @param text              the text
     * @return the string
     */
    public static String rsaEncode(String publicCertificate, String text) {
        try {
            byte[] publicBytes = baseStrToByte(publicCertificate);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PublicKey pubKey = keyFactory.generatePublic(keySpec);
            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance(ALGORITHM);
            // encrypt the plain text using the public key
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] cipherBytes = cipher.doFinal(text.getBytes(CHAR_SET));
            return baseByteToStr(cipherBytes);
        } catch (Exception e) {
            logger.error("publicCertificate:{}  \r\n  text:{}", publicCertificate, text, e);
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(rsaEncode("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmyPbsHrbTDqXcRLhziwstnIWxf3CWSEEmIsTThdFZC3gsLeMhoPRG9hoVKNGTt+5THhc9gzUOUHnvxBmm903rMun4eK1sg+FIkanbys66b6zUnvuBCPeY51ZZsROz2yca5AeNRUgAyOTf0spCeU4KQURGonOtvR3jWOQXh6LBW3L6p+XcOx1eJrg2vQvRjxReSANFqzZtIqAWy+Ejp9Rg1f3WseA4qApp3AHyGTJy6lsebr3VyjgdF6R55PAALHvz3GLY1tsy4pWxP1MJ6UOuh4vAtRVhyYOHxt4gSy1ZIdApMuYU5QUUCywCNuhGoruB2dBwxkymKIqXa8vi25NiQIDAQAB","123456"));
//        System.out.println(rsaDecode("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCbI9uwettMOpdxEuHOLCy2chbF/cJZIQSYixNOF0VkLeCwt4yGg9Eb2GhUo0ZO37lMeFz2DNQ5Qee/EGab3Tesy6fh4rWyD4UiRqdvKzrpvrNSe+4EI95jnVlmxE7PbJxrkB41FSADI5N/SykJ5TgpBREaic629HeNY5BeHosFbcvqn5dw7HV4muDa9C9GPFF5IA0WrNm0ioBbL4SOn1GDV/dax4DioCmncAfIZMnLqWx5uvdXKOB0XpHnk8AAse/PcYtjW2zLilbE/UwnpQ66Hi8C1FWHJg4fG3iBLLVkh0Cky5hTlBRQLLAI26Eaiu4HZ0HDGTKYoipdry+Lbk2JAgMBAAECggEAAueYbTJBq/MpYyKMaS7XzU3Zyg4gHvPWA+alCgMNciyZ4+kjMmC3sAbSCOqlLiR0x1R2Fh0Y9fOl+4RwDWFGZx/Jhlp3VoIBTGoy/UB7lK/faDm93o85h9cvet54T3HRbxdLz33e+Ma9iVu5L8WeSBtU4zCwbCnBLsZ4p/XNr8sY373bHXtWvYofUB/3awvb+auYlEZOBdYbor9zys7Zm5u6poDEbz0smCM07JjB6MTeuXwvIoTDQGscgI8b/GAh1YIDqJx48R5DuNeX7iKO5AJDPqOlQJT8t1NdfJDrlkYN8/XQomL6qrMfZGuEz1Be3+D1J2zXwl9axpdDICx0kQKBgQDUB/SniDPnd6FuP8LHVwNSlND7CfVebWNcmR4BZvtioOCFe4N1FeNOhPDZbtvQVBEBIMN2IZuWemNamKv4KBfTdShp6BSUzE/KsnI3CUG7yUnWOAtVu1sX7A5olWV1yWR0IgGR1VeX+cPUOB19PuhQOk4NgM6vAJJgcIxwtd1TUQKBgQC7T74v7ptjBmJOqUlxHJF6Jv7O5a7tK5GeB3ABaOUjtAla21hUyOqL4GSwdsrkaD8DYippdgpgfz0d6BHw5cgzZQkouQNbjiRVydsvC7NR/OgmFIz87pxHbB73KQo2o0lZNm9SAHokhLNE1dRNf11qZk3VWOKEGv07qwstUXWYuQKBgHaI1A9sp4e5a3gVETEbxfG+3G3bjV7yzF+SAiJKjjL/OUWmXUFxsRfOXk9QGHcI6FC3Hk7GTxL67NxTCaC72UYP8z3xzr+40MrCo/N8q1DuIOcvgba1/SEMiKmTC5ujsRLzh+kdWdDOgtn7XRENwBZJ4iTOY72WFj7v7LN+GHNhAoGAE1LZswYxn5ikAatzOSkSVQC63stRLYSGJEBuLKcOpI1JPcdNKIoFsGJ44L+QlNmwToANEg4saeIWgwRS/YAnFC5DMKFNmF9knjkR1JunZzjpFiyekuVm1/Nuil8Af7x+r6Zu+42zDBtohxxsJ4aRM43UT8M4sxo5r7MolwdFU3kCgYBBMPJv9C2FWV9E4ozqNGKi6u/g4yB6vUZSbEtw8d6dCQ4B+0L3gelaJMY7C0JmX+jZxLTnQlhnHlzbWUDD96jT55focQejz78WZMq/3wMCXWbtEoOtovuzoYlJ6nrdhPzmk3Ncd62LxZgl+FProw8pCL05JlQu5+C1xshgedz6KQ==","a0rwM62idnojt17HWKK6Md59Bycvp4GIcBAsJj31wpfdlovv1ygVP4rvD2Z+yheVP7pAdk2J+x0I4UVNvV9nZZiIIx3Q99WcO1a4w6gH8n1eM6r2v0+fJstuDqPKFBmrA1RCmJ8lZvepANUlVR76Q4+yPh/BWP6R4vMw9DamwmGHyz9R+Uud5ZW31EGqExGNoY7zP4HJ7mK6C7mJoDTjL6WSwJgXtnvI4eKo0YuGK0c7WX46S61oOEXdCWb3++LqXWTAM7XoOhRr8cVKCD1rhfoeoToz2tPVarKJ3yoUl7hWCIGRtuavEOjLfkMYbeqwi15oph4PxIjx8B2o0kx5bQ=="));
    }

    /**
     * Rsa decode string.
     *
     * @param privateCertificate the private certificate
     * @param text               the text
     * @return the string
     */
    public static String rsaDecode(String privateCertificate, String text) {
        try {
            byte[] privateBytes = baseStrToByte(privateCertificate);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
            PrivateKey priKey = keyFactory.generatePrivate(keySpec);
            byte[] cipherText;
            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance(ALGORITHM);
            // encrypt the plain text using the public key
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            byte[] textbyte = baseStrToByte(text);
            cipherText = cipher.doFinal(textbyte);
            return new String(cipherText, CHAR_SET);
        }catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            // 算法不支持
            throw new RuntimeException("不支持的解密算法", e);
        } catch (InvalidKeyException e) {
            // 密钥无效
            throw new RuntimeException("无效的解密密钥", e);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            // 解密失败
            throw new RuntimeException("解密失败：可能是密钥、算法或数据错误", e);
        }  catch (Exception e2) {
            logger.error("privateCertificate:{}  \r\n  text:{}", privateCertificate, text, e2);
        }
        return null;
    }


    /**
     * @param encodedString encodedString
     * @return byte[]
     */
    private static byte[] baseStrToByte(String encodedString) {
        if (StringUtils.isEmpty(encodedString)) {
            return new byte[0];
        }
        try {
            // 尝试标准解码
            return Base64.getDecoder().decode(encodedString);
        } catch (IllegalArgumentException e) {
            // 尝试修复填充
            String fixedEncoding = encodedString;
            switch (encodedString.length() % 4) {
                case 2:
                    fixedEncoding += "==";
                    break;
                case 3:
                    fixedEncoding += "=";
                    break;
            }

            return Base64.getDecoder().decode(fixedEncoding);
        }
    }


    /**
     * @param bytes bytes
     * @return String
     */
    private static String baseByteToStr(byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }
}
